Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

object-observer

Package Overview
Dependencies
Maintainers
1
Versions
95
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

object-observer

object-observer utility provides simple means to (deeply) observe specified object/array changes; implemented via native Proxy; changes delivered in a synchronous way

  • 2.9.4
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
135
increased by11.57%
Maintainers
1
Weekly downloads
 
Created
Source

GitHub npm Travis Codecov Codacy

Summary

object-observer provides a deep observation of a changes performed on an object/array graph.

Main aspects:

  • implemented via native Proxy (revokable)
  • observation is 'deep', yielding changes from a sub-graphs too
  • nested objects of the observable graph are observables too
  • changes delivered in a synchronous way
  • original objects are cloned while turned into Observables
  • arrays specifics:
    • generic object-like mutations supported
    • intrinsic Array mutation methods supported: pop, push, shift, unshift, reverse, sort, fill, splice
    • massive mutations delivered in a single callback, usually having an array of an atomic changes
  • intrinsic mutation methods of Map, WeakMap, Set, WeakSet (set, delete) etc are not observed (see this issue for more details)
  • following host objects (and their extensions) are actively checked and NOT cloned / turned into observables: Date, Blob, Error
Support matrix: CHROME61+ | FIREFOX60+ | EDGE16+ | NODE JS 8.10.0+
Performance report can be found here
Last versions (full changelog is here)
  • 2.9.4

    • implemented Issue no. 31 - added option to observe pathsOf, direct properties of a specific path only
  • 2.8.0

    • officially publishing and documenting Issue no. 33 - any nested object of an Observable graph is observable in itself
  • 2.7.0

    • implemented Issue no. 32 - revokation part removed (underlying proxies are still revokable, for any possible future need)
    • implemented Issue no. 33 - any nested object of an Observable graph is observable in itself - it may be observed/unobserved, it provides relative paths when observed etc.

For a short preview you may want to play with this JSFiddle.

Loading the Library

object-observer provided as an ES6 module. In NodeJS environment, that is not yet fully supporting ES6 modules, use the dedicated distribution as in example below.

Once NodeJS (presumable 13.11.0 going to LTS) will add a full support for ES6 modules, this special distribution will be removed.

//  browser
import { Observable } from 'dist/object-observer.min.js';

//  NodeJS (when NodeJS will fully support ES6 modules syntax - this one will be removed)
let Observable = require('./dist/node/object-observer').Observable;

API

Library implements Observable API as it is defined here.

Examples

Objects
let order = { type: 'book', pid: 102, ammount: 5, remark: 'remove me' },
    observableOrder = Observable.from(order);

observableOrder.observe(changes => {
    changes.forEach(change => {
        console.log(change);
    });
});


observableOrder.ammount = 7;
//  { type: 'update', path: ['ammount'], value: 7, oldValue: 5, object: observableOrder }


observableOrder.address = {
    street: 'Str 75',
    apt: 29
};
//  { type: "insert", path: ['address'], value: { ... }, object: observableOrder }


observableOrder.address.apt = 30;
//  { type: "update", path: ['address','apt'], value: 30, oldValue: 29, object: observableOrder.address }


delete observableOrder.remark;
//  { type: "delete", path: ['remark'], oldValue: 'remove me', object: observableOrder }
Arrays
let a = [ 1, 2, 3, 4, 5 ],
    observableA = Observable.from(a);

observableA.observe(changes => {
    changes.forEach(change => {
        console.log(change);
    });
});

//  observableA = [ 1, 2, 3, 4, 5 ]
observableA.pop();
//  { type: 'delete', path: [4], oldValue: 5, object: observableA }


//  now observableA = [ 1, 2, 3, 4 ]
//  following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.push('a', 'b');
//  { type: 'insert', path: [4], value: 'a', object: observableA }
//  { type: 'insert', path: [5], value: 'b', object: observableA }


//  now observableA = [1, 2, 3, 4, 'a', 'b']
observableA.shift();
//  { type: 'delete', path: [0], oldValue: 1, object: observableA }


//  now observableA = [ 2, 3, 4, 'a', 'b' ]
//  following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.unshift('x', 'y');
//  { type: 'insert', path: [0], value: 'x', object: observableA }
//  { type: 'insert', path: [1], value: 'y', object: observableA }


//  now observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.reverse();
//  { type: 'reverse', path: [], object: observableA } (see below and exampe of this event for nested array)


//  now observableA = [ 'b', 'a', 4, 3, 2 ]
observableA.sort();
//  { type: 'shuffle', path: [], object: observableA } (see below and exampe of this event for nested array)


//  observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.fill(0, 0, 1);
//  { type: 'update', path: [0], value: 0, oldValue: 2, object: observableA }


//  observableA = [ 0, 3, 4, 'a', 'b' ]
//  the following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.splice(0, 1, 'x', 'y');
//  { type: 'update', path: [0], value: 'x', oldValue: 0, object: observableA }
//  { type: 'insert', path: [1], value: 'y', object: observableA }


let customer = { orders: [ ... ] },
    oCustomer = Observable.from(customer);

//  sorting the orders array, pay attention to the path in the event
oCustomer.orders.sort();
//  { type: 'shuffle', path: ['orders'], object: oCustomer.orders }


oCustomer.orders.reverse();
//  { type: 'reverse', path: ['orders'], object: oCustomer.orders }

Arrays notes: Some of array operations are effectively moving/reindexing the whole array (shift, unshift, splice, reverse, sort). In cases of massive changes touching presumably the whole array I took a pessimistic approach with a special non-detailed events: 'reverse' for reverse, 'shuffle' for sort. The rest of these methods I'm handling in an optimistic way delivering the changes that are directly related to the method invocation, while leaving out the implicit outcomes like reindexing of the rest of the Array.

Observation options
let user = {
	    firstName: 'Aya',
	    lastName: 'Guller',
	    address: {
	    	city: 'of mountaineers',
	    	street: 'of the top ridges',
        block: 123,
        extra: {
          data: {}
        }
	    }
    },
    oUser = Observable.from(user);

//  path
//
//  going to observe ONLY the changes of 'firstName'
oUser.observe(changes => {}, {path: 'firstName'});

//  going to observe ONLY the changes of 'address.city'
oUser.observe(changes => {}, {path: 'address.city'});

//  pathsOf
//
//  going to observe the changes of 'address' own properties ('city', 'block') but not else
oUser.observe(changes => {}, {pathsOf: 'address'});
//  here we'll be notified on changes of
//    address.city
//    address.extra

//  pathsFrom
//
//  going to observe the changes from 'address' and deeper
oUser.observe(changes => {}, {pathsFrom: 'address'});
//  here we'll be notified on changes of
//    address
//    address.city
//    address.extra
//    address.extra.data

Keywords

FAQs

Package last updated on 24 May 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc